From 62096ebd16887f300640c954a10d23db017d1463 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 11 Jun 2022 07:05:27 +0200 Subject: [PATCH] filterlistmodel: Add ::item-type and ::n-items With tests! --- gtk/gtkfilterlistmodel.c | 69 ++++++++++++++++++++-- testsuite/gtk/filterlistmodel-exhaustive.c | 28 +++++++++ testsuite/gtk/filterlistmodel.c | 29 +++++---- 3 files changed, 110 insertions(+), 16 deletions(-) diff --git a/gtk/gtkfilterlistmodel.c b/gtk/gtkfilterlistmodel.c index fdf9a4a41e..17074a7025 100644 --- a/gtk/gtkfilterlistmodel.c +++ b/gtk/gtkfilterlistmodel.c @@ -43,7 +43,9 @@ enum { PROP_0, PROP_FILTER, PROP_INCREMENTAL, + PROP_ITEM_TYPE, PROP_MODEL, + PROP_N_ITEMS, PROP_PENDING, NUM_PROPERTIES }; @@ -206,14 +208,18 @@ gtk_filter_list_model_emit_items_changed_for_changes (GtkFilterListModel *self, gtk_bitset_difference (changes, old); if (!gtk_bitset_is_empty (changes)) { - guint min, max; + guint min, max, removed, added; min = gtk_bitset_get_minimum (changes); max = gtk_bitset_get_maximum (changes); + removed = gtk_bitset_get_size_in_range (old, min, max); + added = gtk_bitset_get_size_in_range (self->matches, min, max); g_list_model_items_changed (G_LIST_MODEL (self), min > 0 ? gtk_bitset_get_size_in_range (self->matches, 0, min - 1) : 0, - gtk_bitset_get_size_in_range (old, min, max), - gtk_bitset_get_size_in_range (self->matches, min, max)); + removed, + added); + if (removed != added) + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]); } gtk_bitset_unref (changes); gtk_bitset_unref (old); @@ -286,6 +292,8 @@ gtk_filter_list_model_items_changed_cb (GListModel *model, case GTK_FILTER_MATCH_ALL: g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added); + if (removed != added) + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]); return; case GTK_FILTER_MATCH_SOME: @@ -316,6 +324,8 @@ gtk_filter_list_model_items_changed_cb (GListModel *model, g_list_model_items_changed (G_LIST_MODEL (self), position > 0 ? gtk_bitset_get_size_in_range (self->matches, 0, position - 1) : 0, filter_removed, filter_added); + if (filter_removed != filter_added) + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]); } static void @@ -364,10 +374,18 @@ gtk_filter_list_model_get_property (GObject *object, g_value_set_boolean (value, self->incremental); break; + case PROP_ITEM_TYPE: + g_value_set_gtype (value, gtk_filter_list_model_get_item_type (G_LIST_MODEL (self))); + break; + case PROP_MODEL: g_value_set_object (value, self->model); break; + case PROP_N_ITEMS: + g_value_set_uint (value, gtk_filter_list_model_get_n_items (G_LIST_MODEL (self))); + break; + case PROP_PENDING: g_value_set_uint (value, gtk_filter_list_model_get_pending (self)); break; @@ -415,7 +433,10 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self, self->strictness = new_strictness; gtk_filter_list_model_stop_filtering (self); if (n_before > 0) - g_list_model_items_changed (G_LIST_MODEL (self), 0, n_before, 0); + { + g_list_model_items_changed (G_LIST_MODEL (self), 0, n_before, 0); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]); + } } break; @@ -423,8 +444,17 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self, switch (self->strictness) { case GTK_FILTER_MATCH_NONE: - self->strictness = new_strictness; - g_list_model_items_changed (G_LIST_MODEL (self), 0, 0, g_list_model_get_n_items (self->model)); + { + guint n_items; + + self->strictness = new_strictness; + n_items = g_list_model_get_n_items (self->model); + if (n_items > 0) + { + g_list_model_items_changed (G_LIST_MODEL (self), 0, 0, n_items); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]); + } + } break; case GTK_FILTER_MATCH_ALL: self->strictness = new_strictness; @@ -460,6 +490,7 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self, g_clear_pointer (&self->matches, gtk_bitset_unref); g_list_model_items_changed (G_LIST_MODEL (self), start, n_before - end - start, n_after - end - start); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]); } } break; @@ -571,6 +602,18 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class) FALSE, GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkFilterListModel:item-type: + * + * The type of items. See [method@Gio.ListModel.get_item_type]. + * + * Since: 4.8 + **/ + properties[PROP_ITEM_TYPE] = + g_param_spec_gtype ("item-type", NULL, NULL, + G_TYPE_OBJECT, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** * GtkFilterListModel:model: (attributes org.gtk.Property.get=gtk_filter_list_model_get_model org.gtk.Property.set=gtk_filter_list_model_set_model) * @@ -581,6 +624,18 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class) G_TYPE_LIST_MODEL, GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkFilterListModel:n-items: + * + * The number of items. See [method@Gio.ListModel.get_n_items]. + * + * Since: 4.8 + **/ + properties[PROP_N_ITEMS] = + g_param_spec_uint ("n-items", NULL, NULL, + 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** * GtkFilterListModel:pending: (attributes org.gtk.Property.get=gtk_filter_list_model_get_pending) * @@ -737,6 +792,8 @@ gtk_filter_list_model_set_model (GtkFilterListModel *self, if (removed > 0 || added > 0) g_list_model_items_changed (G_LIST_MODEL (self), 0, removed, added); + if (removed != added) + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]); } diff --git a/testsuite/gtk/filterlistmodel-exhaustive.c b/testsuite/gtk/filterlistmodel-exhaustive.c index b7366f4fb6..084f1d301d 100644 --- a/testsuite/gtk/filterlistmodel-exhaustive.c +++ b/testsuite/gtk/filterlistmodel-exhaustive.c @@ -75,6 +75,9 @@ assert_items_changed_correctly (GListModel *model, { guint i, n_items; + //sanity check that we got all notifies + g_assert_cmpuint (g_list_model_get_n_items (compare), ==, GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (compare), "last-notified-n-items"))); + //g_print ("%s => %u -%u +%u => %s\n", model_to_string (compare), position, removed, added, model_to_string (model)); g_assert_cmpint (g_list_model_get_n_items (model), ==, g_list_model_get_n_items (compare) - removed + added); @@ -127,6 +130,21 @@ assert_items_changed_correctly (GListModel *model, } } +static void +assert_n_items_notified_properly (GListModel *model, + GParamSpec *pspec, + GListModel *compare) +{ + g_assert_cmpuint (g_list_model_get_n_items (model), !=, GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (compare), "last-notified-n-items"))); + + /* These should hve been updated in items-changed, which should have been emitted first */ + g_assert_cmpuint (g_list_model_get_n_items (model), ==, g_list_model_get_n_items (compare)); + + g_object_set_data (G_OBJECT (compare), + "last-notified-n-items", + GUINT_TO_POINTER (g_list_model_get_n_items (model))); +} + static GtkFilterListModel * filter_list_model_new (GListModel *source, GtkFilter *filter) @@ -154,6 +172,16 @@ filter_list_model_new (GListModel *source, (GClosureNotify) g_object_unref, 0); + g_object_set_data (G_OBJECT (check), + "last-notified-n-items", + GUINT_TO_POINTER (g_list_model_get_n_items (G_LIST_MODEL (check)))); + g_signal_connect_data (model, + "notify::n-items", + G_CALLBACK (assert_n_items_notified_properly), + g_object_ref (check), + (GClosureNotify) g_object_unref, + 0); + return model; } diff --git a/testsuite/gtk/filterlistmodel.c b/testsuite/gtk/filterlistmodel.c index cd109c2e0b..d35b73f74b 100644 --- a/testsuite/gtk/filterlistmodel.c +++ b/testsuite/gtk/filterlistmodel.c @@ -143,6 +143,14 @@ items_changed (GListModel *model, } } +static void +notify_n_items (GObject *object, + GParamSpec *pspec, + GString *changes) +{ + g_string_append_c (changes, '*'); +} + static void free_changes (gpointer data) { @@ -171,6 +179,7 @@ new_model (guint size, changes = g_string_new (""); g_object_set_qdata_full (G_OBJECT(result), changes_quark, changes, free_changes); g_signal_connect (result, "items-changed", G_CALLBACK (items_changed), changes); + g_signal_connect (result, "notify::n-items", G_CALLBACK (notify_n_items), changes); return result; } @@ -248,7 +257,7 @@ test_empty_set_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "1 2 3 4 5 6"); - assert_changes (filter, "6-4"); + assert_changes (filter, "6-4*"); g_object_unref (filter); filter = new_model (10, NULL, NULL); @@ -256,7 +265,7 @@ test_empty_set_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, ""); - assert_changes (filter, "0-10"); + assert_changes (filter, "0-10*"); g_object_unref (filter); filter = new_model (10, NULL, NULL); @@ -272,7 +281,7 @@ test_empty_set_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "4 5 6 7 8 9 10"); - assert_changes (filter, "0-3"); + assert_changes (filter, "0-3*"); g_object_unref (filter); filter = new_model (10, NULL, NULL); @@ -280,7 +289,7 @@ test_empty_set_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, ""); - assert_changes (filter, "0-10"); + assert_changes (filter, "0-10*"); g_object_unref (filter); filter = new_model (10, NULL, NULL); @@ -288,7 +297,7 @@ test_empty_set_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "3 4 5 6 7"); - assert_changes (filter, "0-10+5"); + assert_changes (filter, "0-10+5*"); g_object_unref (filter); filter = new_model (10, NULL, NULL); @@ -296,7 +305,7 @@ test_empty_set_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "1 2 8 9 10"); - assert_changes (filter, "2-5"); + assert_changes (filter, "2-5*"); g_object_unref (filter); } @@ -320,19 +329,19 @@ test_change_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "1 2 3 4 5 6"); - assert_changes (filter, "3-2+3"); + assert_changes (filter, "3-2+3*"); custom = GTK_FILTER (gtk_custom_filter_new (is_smaller_than, GUINT_TO_POINTER (6), NULL)); gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "1 2 3 4 5"); - assert_changes (filter, "-5"); + assert_changes (filter, "-5*"); custom = GTK_FILTER (gtk_custom_filter_new (is_larger_than, GUINT_TO_POINTER (4), NULL)); gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "5 6 7 8 9 10"); - assert_changes (filter, "0-5+6"); + assert_changes (filter, "0-5+6*"); custom = GTK_FILTER (gtk_custom_filter_new (is_not_near, GUINT_TO_POINTER (2), NULL)); gtk_filter_list_model_set_filter (filter, custom); @@ -344,7 +353,7 @@ test_change_filter (void) gtk_filter_list_model_set_filter (filter, custom); g_object_unref (custom); assert_model (filter, "1 7 8 9 10"); - assert_changes (filter, "0-2+1"); + assert_changes (filter, "0-2+1*"); g_object_unref (filter); } -- 2.30.2